package com.hyh.shiro.component;

import com.hyh.shiro.entity.UserBean;
import com.hyh.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Optional;

/**
 * 核心组件:认证+授权
 *
 * @author Summerday
 */

public class AuthRealm extends AuthorizingRealm {

    private static final Logger log = LoggerFactory.getLogger(AuthRealm.class);

    private static final String SESSION_KEY = "USER_SESSION";

    @Resource
    private UserService userService;

    /**
     * 只有需要验证权限时才会调用, 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取user
        Session session = SecurityUtils.getSubject().getSession();
        UserBean user = (UserBean) session.getAttribute(SESSION_KEY);
        // 权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 定义role和permission
        info.addRole(user.getRole());
        info.addStringPermissions(Arrays.asList(user.getPermission().split(",")));
        return info;
    }

    /**
     * 登录时调用该方法
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        //获取user
        String username = (String) auth.getPrincipal();
        // 如果user为空,抛出UnknownAccountException异常
        UserBean user = Optional
                .ofNullable(userService.getUser(username))
                .orElseThrow(UnknownAccountException::new);
        //账号锁定
        if(Boolean.TRUE.equals(user.isLocked())){
            throw new LockedAccountException();
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, user.getPassword(), getName());
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute(SESSION_KEY, user);
        return info;
    }
}
